package com.zj.base.base_fg;

import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.util.Log;

import java.util.List;

/**
 * Created by ZhaoJie on 2018/7/7.
 */

public abstract class FragmentHelper implements FragmentOperator {

    private int currentItem = -1, oldItem = -1;
    private FragmentManager fragmentManager;
    private final List<Fragment> mFragments;
    private int containId;
    private long clickTime;
    private FragmentObserver fragmentObserver;

    public FragmentHelper(FragmentManager manager, int containId, List<Fragment> fragments) {
        this.mFragments = fragments;
        this.fragmentManager = manager;
        this.containId = containId;
    }

    /**
     * 如果在切换Fragment时会销毁一些耗时操作，可能会引起ANR，
     * 设置此回调将暂时暂停切换操作，当耗时操作处理完成后，调用观察器内的StateChange对象以继续切换操作；
     */
    public void setFragmentObserver(FragmentObserver observer) {
        this.fragmentObserver = observer;
    }

    /**
     * @param showItem 显示的item
     */
    protected void showFragment(int showItem) {
        if (System.currentTimeMillis() - clickTime < 300) {
            return;
        }
        clickTime = System.currentTimeMillis();
        if (showItem == currentItem) {
            whenShowSameFragment(showItem);
        } else {
            FragmentTransaction transaction = fragmentManager.beginTransaction();
            beginTransaction(transaction, currentItem, showItem, mFragments.size() - 1);
            if (whenShowNotSameFragment(showItem)) {
                currentItem = showItem;
                performSelectItem(transaction);
            }
        }
    }

    /**
     * 隐藏当前的fragment,显示要显示的fragment
     *
     * @param transaction
     */
    private void performSelectItem(FragmentTransaction transaction) {
        if (currentItem == oldItem) return;
        hideOldFragments(transaction);
        showNewFragment(transaction);
        transaction.commit();
        syncSelectState(currentItem);
        oldItem = currentItem;
    }

    private void showNewFragment(final FragmentTransaction transaction) {
        final Fragment frg = mFragments.get(currentItem);
        if (frg.isAdded()) {
            frg.onResume();
            if (fragmentObserver == null)
                transaction.show(frg);
            else {
                fragmentObserver.beforeHiddenChange(frg, false, new StateChange() {
                    @Override
                    public void change() {
                        transaction.show(frg);
                    }
                });
            }

        } else {
            fragmentManager.beginTransaction().add(containId, frg, frg.getClass().getSimpleName()).show(frg).commit();
        }
    }

    private void hideOldFragments(final FragmentTransaction transaction) {
        for (int i = 0; i < mFragments.size(); i++) {
            if (currentItem != i) {
                final Fragment oldFragment = mFragments.get(i);
                if (oldFragment.isAdded()) {
                    if (oldFragment.isResumed()) {
                        oldFragment.onPause();
                        oldFragment.onStop();
                    }
                    if (!oldFragment.isHidden()) {
                        if (fragmentObserver == null)
                            transaction.hide(oldFragment);
                        else {
                            fragmentObserver.beforeHiddenChange(oldFragment, true, new StateChange() {
                                @Override
                                public void change() {
                                    transaction.hide(oldFragment);
                                }
                            });
                        }
                    }
                } else {
                    fragmentManager.beginTransaction().add(containId, oldFragment, oldFragment.getClass().getSimpleName()).hide(oldFragment).commit();
                }
            }
        }
    }
}
